
package com.x52im.rbchat.network.http.async;

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

import com.eva.epc.common.util.CommonUtils;
import com.eva.framework.dto.DataFromServer;
import com.x52im.rbchat.MyApplication;
import com.x52im.rbchat.network.http.HttpRestHelper;
import com.x52im.rainbowchat.http.logic.dto.RosterElementEntity;
import com.x52im.rbchat.utils.PreferencesToolkits;
import com.x52im.rbchat.utils.ToolKits;

import java.util.ArrayList;

/**
 * 查询离线加好友请求（异步）.
 * <p>
 * 本类目前仅用于登陆成功后，首页上刷新离线的“加好友请求”未读数及列表中的Alarm的显示。
 * <p>不能使用DataLoadingAsyncTask类来处理的原因在于它里面涉及到UI，所以想在
 * 非Activity的context的情况下就会出错哦。
 * 
 * @author Jack Jiang(http://www.52im.net/space-uid-1.html)
 * @version 1.0
 */
public class QueryOfflineFriendsReqAsync extends AsyncTask<String, Integer, DataFromServer> {
	private Context context = null;

	public QueryOfflineFriendsReqAsync(Context context) {
		this.context = context;
	}

	@Override
	protected DataFromServer doInBackground(String... parems) {
		return queryOfflineBeAddFriendsReq(context);
	}

	protected void onPostExecute(DataFromServer dfs) {
		// 取离线加好友请数据成功
		if(dfs != null && dfs.isSuccess()) {
			ArrayList<RosterElementEntity> srcFriendsReq = HttpRestHelper.parseGetOfflineAddFriendsReqFromServer((String)dfs.getReturnValue());
			if(srcFriendsReq != null && srcFriendsReq.size() > 0) {
				Log.d(QueryOfflineFriendsReqAsync.class.getSimpleName(), "离线好友请求读取成功，共有请求数：" + srcFriendsReq.size());

				// 最新一条好友请求的数据（服务端返回的加好友请求通知是按发起时间DESC逆序排列的，索引0就是最新的请求，详见HTTP接口说明）
				RosterElementEntity latestRee = srcFriendsReq.get(0);
				// 自v4.3以后，本字段存放的是时间戳，而非人类可读的时间字串
				long reqTime = CommonUtils.getLongValue(latestRee.getEx10());

				// 计算未读的好友请求（当用户点击进入好友请求列表时，此时间点之前的所有请求表示"已读"，
				// 且会同时存储此次查看时最新的那条请求的时间戳，下次在未进入请求列表界面的情况下，将
				// 据此值计算未读条数（计算方法是：当目前所有服务端同步过来的未处理请求中，时间戳大于
				// 上次存储的，即表示这是此后"未读"的，累加起来便是当前的"未读"总数啦）
				int unreadTotlaCount = calculateUnreadFriendReqCount(srcFriendsReq);
				
				// 添加到首页通知的数据模型中
				MyApplication.getInstance(context).getIMClientManager().getAlarmsProvider()
					.addAddFriendReqMergeAlarm(latestRee.getUser_uid(), latestRee.getNickname(), reqTime, unreadTotlaCount, true, false);
				// 设置好友请求全局缓存中的总未读数
				MyApplication.getInstance2().getIMClientManager().getFriendsReqProvider().setUnreadCount(unreadTotlaCount,true);
			}
		}
		else {
			Log.e(QueryOfflineFriendsReqAsync.class.getSimpleName(), "离线好友请求从服务端获取失败.");
		}
	}

	/**
	 * 从从服务端http接口中加载过来的全部未处理好友请求数据中，计算出当前"未读"总数。
	 * <p>
	 * 具体的计算和实现逻辑是：当用户点击进入好友请求列表时，此时间点之前的所有请求表示"已读"，且会同时存储此次查
	 * 看时最新的那条请求的时间戳，下次在未进入请求列表界面的情况下，将据此值计算未读条数（计算方法是：当目前所有
	 * 服务端同步过来的未处理请求中，时间戳大于上次存储的，即表示这是此后"未读"的，累加起来便是当前的"未读"总数啦。
	 * </p>
	 *
	 * @param srcFriendsReqs 未处理的所有好友请求列表（服务端返回的是按DESC请求时间逆序排列的）
	 * @return 大于或等于0的整数
	 */
	public static int calculateUnreadFriendReqCount(ArrayList<RosterElementEntity> srcFriendsReqs) {

		long t = System.currentTimeMillis();

		int unreadTotlaCount = 0;
		long lastLatestReqTimestamp = PreferencesToolkits.getHasReadLatestFriendReqTimestamp(MyApplication.getInstance2());
		// 当不存在已读记录时，直接就把整个未处理数当作未读数
		if (lastLatestReqTimestamp <= 0) {
			unreadTotlaCount = srcFriendsReqs.size();
		}
		else {
			for (RosterElementEntity req : srcFriendsReqs) {
				long theTimestamp = CommonUtils.getLongValue(req.getEx10(), 0L);
				// 如果服务端返回的请求数据中，不存在或不正确的时间戳，就跳过此条
				if (theTimestamp <= 0) {
					continue;
				}

				// 当请求时间戳大于上次已读的，就表示这是新的"未读"，未读总数+1
				if (theTimestamp > lastLatestReqTimestamp) {
					unreadTotlaCount += 1;
				}
				// 当请求时间戳小于或等于上次的时，表示这些已是上次已读过的，由于整个未
				// 处理列表是是按时间逆序排列，所以可以认为没有必要再继续余下的循环判断了
				else {
					break;
				}
			}
		}

		Log.i(QueryOfflineFriendsReqAsync.class.getSimpleName(), "计算出的本次\"未读\"加好友请求总数是 "
				+unreadTotlaCount+"，总耗时"+(System.currentTimeMillis()-t)+"ms !");

		return unreadTotlaCount;
	}

	/**
	 * 查询离线加好友请求数据.
	 * 
	 * @param context
	 * @return
	 */
	public static DataFromServer queryOfflineBeAddFriendsReq(Context context) {
		RosterElementEntity localUserInfo = MyApplication.getInstance(context).getIMClientManager().getLocalUserInfo();
		// ## Bug FIX:
		// ##  以下判断为容错处理，根据Bug上报统计，当此null出现时基本上就是实时音视频库因手机兼容性出现底层
		// ##  fetal级崩溃而导致，此判断用于友好提示用户并即时让用户退出APP，从而不要让Android APP处于脏现场中
		if(localUserInfo == null) {
			ToolKits.fetalErrorAlert(context);
			return DataFromServer.createDefaultFailed();
		}
		else {
			return HttpRestHelper.submitGetOfflineAddFriendsReqToServer(localUserInfo.getUser_uid());
		}
	}
}